using System;
using Headsight.BPMN2WF.BPMN.Schemas;
using Headsight.BPMN2WF.Testing.TestObjCtors;
using Headsight.BPMN2WF.Transformation;
using Headsight.BPMN2WF.Transformation.BPMN2TransformerMappings.Additions;
using Headsight.BPMN2WF.WF.Simplification;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Headsight.BPMN2WF
{
    [TestClass]
    public class BPMN2WFFactoryTest
    {
        private IBPMN2WFTransformations _bpmn2WfTransformations;

        [TestInitialize]
        public void SetUp()
        {
            _bpmn2WfTransformations = new BPMN2WFTransformations4TestingCtor().Create();
        }

        [TestMethod]
        public void Create_Default()
        {
            var result = BPMN2WFFactory.Create(_bpmn2WfTransformations) as BPMN2WFImpl;

            Assert.IsNotNull(result);
            Verify_BPMN2WFTransformations_true_false(result.BPMN2WFTransformations);
        }

        [TestMethod]
        public void Create_inco_true_true()
        {
            var result = BPMN2WFFactory.Create(_bpmn2WfTransformations, true, new tDefinitions()) as BPMN2WFImpl;

            Assert.IsNotNull(result);
            Verify_BPMN2WFTransformations_true_true(result.BPMN2WFTransformations);
        }

        [TestMethod]
        public void Create_inco_false_false()
        {
            var result = BPMN2WFFactory.Create(_bpmn2WfTransformations, false, null) as BPMN2WFImpl;

            Assert.IsNotNull(result);
            Verify_BPMN2WFTransformations_false_false(result.BPMN2WFTransformations);
        }

        [TestMethod]
        public void Create_inco_true_false()
        {
            var result = BPMN2WFFactory.Create(_bpmn2WfTransformations, true, null) as BPMN2WFImpl;

            Assert.IsNotNull(result);
            Verify_BPMN2WFTransformations_true_false(result.BPMN2WFTransformations);
        }

        [TestMethod]
        public void Create_inco_false_true()
        {
            var result = BPMN2WFFactory.Create(_bpmn2WfTransformations, false, new tDefinitions()) as BPMN2WFImpl;

            Assert.IsNotNull(result);
            Verify_BPMN2WFTransformations_false_true(result.BPMN2WFTransformations);
        }

        private void Verify_BPMN2WFTransformations_true_true(IBPMN2WFTransformations actual)
        {
            Assert.IsNotNull(actual);

            actual = VerifyExceptionWrapper(actual);

            var wrapper1 = actual as BPMN2WFTransformationsSimplifierWrapper;
            Assert.IsNotNull(wrapper1);

            var wrapper2 = wrapper1.Delegate as BPMN2WFTransformationsLayouterWrapper;
            Assert.IsNotNull(wrapper2);

            Verify_BPMN2WFTransformationsFixPart(wrapper2.Delegate);
        }

        private void Verify_BPMN2WFTransformationsFixPart(IBPMN2WFTransformations bpmn2WfTransformations)
        {
            var wrapper3 = bpmn2WfTransformations as BPMN2WFTransformationsResultsCollectorWrapper;
            Assert.IsNotNull(wrapper3);

            var wrapper4 = wrapper3.Delegate as BPMN2WFTransformationsCacheWrapper;
            Assert.IsNotNull(wrapper4);

            Assert.AreSame(_bpmn2WfTransformations, wrapper4.Delegate);
        }

        private void Verify_BPMN2WFTransformations_false_false(IBPMN2WFTransformations actual)
        {
            actual = VerifyExceptionWrapper(actual);
            Verify_BPMN2WFTransformationsFixPart(actual);
        }

        private void Verify_BPMN2WFTransformations_true_false(IBPMN2WFTransformations actual)
        {
            actual = VerifyExceptionWrapper(actual);
            Assert.IsNotNull(actual);

            var wrapper1 = actual as BPMN2WFTransformationsSimplifierWrapper;
            Assert.IsNotNull(wrapper1);

            Verify_BPMN2WFTransformationsFixPart(wrapper1.Delegate);
        }

        private void Verify_BPMN2WFTransformations_false_true(IBPMN2WFTransformations actual)
        {
            actual = VerifyExceptionWrapper(actual);
            Assert.IsNotNull(actual);

            var wrapper1 = actual as BPMN2WFTransformationsLayouterWrapper;
            Assert.IsNotNull(wrapper1);

            Verify_BPMN2WFTransformationsFixPart(wrapper1.Delegate);
        }

        private static IBPMN2WFTransformations VerifyExceptionWrapper(IBPMN2WFTransformations actual)
        {
            var abc = actual as BPMN2WFTransformationsExceptionHandlerWrapper;

            Assert.IsNotNull(abc);
            return abc.Delegate;
        }
    }
}